home *** CD-ROM | disk | FTP | other *** search
/ Aminet 23 / Aminet 23 (1998)(GTI - Schatztruhe)[!][Feb 1998].iso / Aminet / misc / emu / amiSPIMsrc.lha / mips-syscall.c < prev    next >
C/C++ Source or Header  |  1994-02-08  |  31KB  |  1,111 lines

  1. /* SPIM S20 MIPS simulator.
  2.    Execute SPIM syscalls, both in simulator and bare mode.
  3.    Execute MIPS syscalls in bare mode, when running on MIPS systems.
  4.    Copyright (C) 1990-1994 by James Larus (larus@cs.wisc.edu).
  5.    ALL RIGHTS RESERVED.
  6.    Improved by Emin Gun Sirer.
  7.  
  8.    SPIM is distributed under the following conditions:
  9.  
  10.      You may make copies of SPIM for your own use and modify those copies.
  11.  
  12.      All copies of SPIM must retain my name and copyright notice.
  13.  
  14.      You may not sell SPIM or distributed SPIM in conjunction with a
  15.      commerical product or service without the expressed written consent of
  16.      James Larus.
  17.  
  18.    THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  19.    IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  20.    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  21.    PURPOSE. */
  22.  
  23.  
  24. /* $Header: /home/primost/larus/Software/SPIM/RCS/mips-syscall.c,v 1.21 1994/01/18 03:21:45 larus Exp larus $ */
  25.  
  26.  
  27. #include <stdio.h>
  28. #include <sys/types.h>
  29. #include <signal.h>
  30. #ifdef RS
  31. /* This is problem on HP Snakes, which define RS in syscall.h */
  32. #undef RS
  33. #endif
  34. #ifdef mips
  35. #include <syscall.h>
  36. #include <limits.h>
  37. #endif
  38.  
  39. #include "spim.h"
  40. #include "inst.h"
  41. #include "mem.h"
  42. #include "reg.h"
  43. #include "read-aout.h"
  44. #include "sym-tbl.h"
  45. #include "spim-syscall.h"
  46. #include "mips-syscall.h"
  47.  
  48. #ifdef CL_SPIM
  49. #include "cl-except.h"
  50. #endif
  51.  
  52.  
  53. /* Imported variables: */
  54.  
  55. extern int errno;
  56.  
  57.  
  58. /* Imported functions: */
  59.  
  60. #ifdef __STDC__
  61. extern int close (int);
  62. extern int dup (int);
  63. extern int syscall (int, ...);
  64. extern int select ();
  65. #else
  66. extern int close ();
  67. extern int dup ();
  68. extern int syscall ();
  69. extern int select ();
  70. #endif
  71.  
  72.  
  73. /* Local functions: */
  74.  
  75. #ifdef __STDC__
  76. static void do_sigreturn (mem_addr sigptr);
  77. static int reverse_fds (int fd);
  78. static void setup_signal_stack (void);
  79. static int unixsyscall (void);
  80. #else
  81. static void do_sigreturn ();
  82. static int reverse_fds ();
  83. static void setup_signal_stack ();
  84. static int unixsyscall ();
  85. #endif
  86.  
  87. #ifndef mips
  88. #ifndef OPEN_MAX
  89. #define OPEN_MAX 20
  90. #endif
  91. #endif
  92.  
  93. #ifndef NSIG
  94. #define NSIG 128
  95. #endif
  96.  
  97. /* Local variables: */
  98.  
  99. static int prog_sigmask = 0;    /* Copy of sigmask passed to system */
  100.  
  101. #ifdef mips
  102. static mem_addr exception_address[NSIG]; /* trampoline addresses for */
  103.                      /* each signal handler */
  104.  
  105. static struct sigvec sighandler[NSIG]; /* Map to program handlers */
  106. #endif
  107.  
  108. static int prog_fds[OPEN_MAX];    /* Map from program fds to simulator fds */
  109.  
  110. static int fds_initialized = 0;    /* FD map initialized? */
  111.  
  112.  
  113. #define REG_ERR 7
  114.  
  115.  
  116.  
  117. /* Table describing arguments to syscalls. */
  118.  
  119. typedef struct
  120. {
  121.   int syscall_num;
  122.   int syscall_type;
  123.   int arg0;
  124.   int arg1;
  125.   int arg2;
  126.   int arg3;
  127.   int arg4;
  128.   char *syscall_name;
  129. } syscall_desc;
  130.  
  131. enum {BAD_SYSCALL, UNIX_SYSCALL, SPC_SYSCALL};
  132.  
  133. enum {NO_ARG, INT_ARG, ADDR_ARG, STR_ARG, FD_ARG};  /* Type of argument */
  134.  
  135. static syscall_desc syscall_table[] =
  136. {
  137. #ifdef mips
  138.   {SYS_syscall, SPC_SYSCALL, INT_ARG, INT_ARG, INT_ARG, INT_ARG, NO_ARG,
  139.      "syscall"},
  140.   {SYS_exit, SPC_SYSCALL, INT_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "exit"},
  141.   {SYS_fork, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "fork"},
  142.   {SYS_read, UNIX_SYSCALL, FD_ARG, ADDR_ARG, INT_ARG, NO_ARG, NO_ARG, "read"},
  143.   {SYS_write, UNIX_SYSCALL, FD_ARG, STR_ARG, INT_ARG, NO_ARG, NO_ARG, "write"},
  144.   {SYS_open, SPC_SYSCALL, STR_ARG, INT_ARG, INT_ARG, NO_ARG, NO_ARG, "open"},
  145.   {SYS_close, SPC_SYSCALL, FD_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "close"},
  146.   {7, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  147.   {SYS_creat, SPC_SYSCALL, STR_ARG, INT_ARG, NO_ARG, NO_ARG, NO_ARG, "creat"},
  148.   {SYS_link, UNIX_SYSCALL, STR_ARG, STR_ARG, NO_ARG, NO_ARG, NO_ARG, "link"},
  149.   {SYS_unlink, UNIX_SYSCALL, STR_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  150.      "unlink"},
  151.   {SYS_execv, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "execv"},
  152.   {SYS_chdir, UNIX_SYSCALL, STR_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "chdir"},
  153.   {13, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  154.   {SYS_mknod, UNIX_SYSCALL, STR_ARG, INT_ARG, INT_ARG, NO_ARG, NO_ARG,
  155.      "mknod"},
  156.   {SYS_chmod, UNIX_SYSCALL, STR_ARG, INT_ARG, NO_ARG, NO_ARG, NO_ARG, "chmod"},
  157.   {SYS_chown, UNIX_SYSCALL, STR_ARG, INT_ARG, INT_ARG, NO_ARG, NO_ARG,
  158.      "chown"},
  159.   {SYS_brk, SPC_SYSCALL, ADDR_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "brk"},
  160.   {18, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  161.   {SYS_lseek, UNIX_SYSCALL, FD_ARG, INT_ARG, INT_ARG, NO_ARG, NO_ARG, "lseek"},
  162.   {SYS_getpid, UNIX_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "getpid"},
  163.   {SYS_mount, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "mount"},
  164.   {SYS_umount, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "umount"},
  165.   {23, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  166.   {SYS_getuid, UNIX_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "getuid"},
  167.   {25, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  168.   {SYS_ptrace, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "ptrace"},
  169.   {27, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  170.   {28, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  171.   {29, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  172.   {30, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  173.   {31, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  174.   {32, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  175.   {SYS_access, UNIX_SYSCALL, STR_ARG, INT_ARG, NO_ARG, NO_ARG, NO_ARG,
  176.      "access"},
  177.   {34, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  178.   {35, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  179.   {SYS_sync, UNIX_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "sync"},
  180.   {SYS_kill, UNIX_SYSCALL, INT_ARG, INT_ARG, NO_ARG, NO_ARG, NO_ARG, "kill"},
  181.   {SYS_stat, UNIX_SYSCALL, STR_ARG, ADDR_ARG, NO_ARG, NO_ARG, NO_ARG, "stat"},
  182.   {39, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  183.   {SYS_lstat, UNIX_SYSCALL, STR_ARG, ADDR_ARG, NO_ARG, NO_ARG, NO_ARG,
  184.      "lstat"},
  185.   {SYS_dup, SPC_SYSCALL, FD_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "dup"},
  186.   {SYS_pipe, UNIX_SYSCALL, ADDR_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "pipe"},
  187.   {43, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  188.   {SYS_profil, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "profil"},
  189.   {45, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  190.   {46, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  191.   {SYS_getgid, UNIX_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "getgid"},
  192.   {48, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  193.   {49, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  194.   {50, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  195.   {SYS_acct, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "acct"},
  196.   {52, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  197.   {53, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  198.   {SYS_ioctl, UNIX_SYSCALL, FD_ARG, INT_ARG, ADDR_ARG, NO_ARG, NO_ARG,
  199.      "ioctl"},
  200.   {SYS_reboot, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "reboot"},
  201.   {56, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  202.   {SYS_symlink, UNIX_SYSCALL, STR_ARG, STR_ARG, NO_ARG, NO_ARG, NO_ARG,
  203.      "symlink"},
  204.   {SYS_readlink, UNIX_SYSCALL, ADDR_ARG, ADDR_ARG, INT_ARG, NO_ARG, NO_ARG,
  205.      "readlink"},
  206.   {SYS_execve, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "execve"},
  207.   {SYS_umask, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "umask"},
  208.   {SYS_chroot, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "chroot"},
  209.   {SYS_fstat, UNIX_SYSCALL, FD_ARG, ADDR_ARG, NO_ARG, NO_ARG, NO_ARG, "fstat"},
  210.   {63, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  211.   {SYS_getpagesize, UNIX_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  212.      "getpagesize"},
  213.   {SYS_mremap, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "mremap"},
  214.   {SYS_vfork, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "vfork"},
  215.   {67, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  216.   {68, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  217.   {SYS_sbrk, SPC_SYSCALL, INT_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "sbrk"},
  218.   {SYS_sstk, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "sstk"},
  219.   {SYS_mmap, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "mmap"},
  220.   {SYS_vadvise, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  221.      "vadvise"},
  222.   {SYS_munmap, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "munmap"},
  223.   {SYS_mprotect, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  224.      "mprotect"},
  225.   {SYS_madvise, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  226.      "madvise"},
  227.   {SYS_vhangup, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  228.      "vhangup"},
  229.   {77, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  230.   {SYS_mincore, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  231.      "mincore"},
  232.   {SYS_getgroups, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  233.      "getgroups"},
  234.   {SYS_setgroups, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  235.      "setgroups"},
  236.   {SYS_getpgrp, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  237.      "getpgrp"},
  238.   {SYS_setpgrp, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  239.      "setpgrp"},
  240.   {SYS_setitimer, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  241.      "setitimer"},
  242.   {SYS_wait3, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "wait3"},
  243.   {SYS_swapon, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "swapon"},
  244.   {SYS_getitimer, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  245.      "getitimer"},
  246.   {SYS_gethostname, UNIX_SYSCALL, STR_ARG, INT_ARG, NO_ARG, NO_ARG, NO_ARG,
  247.      "gethostname"},
  248.   {SYS_sethostname, UNIX_SYSCALL, STR_ARG, INT_ARG, NO_ARG, NO_ARG, NO_ARG,
  249.      "sethostname"},
  250.   {SYS_getdtablesize, UNIX_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  251.      "getdtablesize"},
  252.   {SYS_dup2, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "dup2"},
  253.   {SYS_getdopt, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  254.      "getdopt"},
  255.   {SYS_fcntl, UNIX_SYSCALL, FD_ARG, INT_ARG, INT_ARG, NO_ARG, NO_ARG, "fcntl"},
  256.   {SYS_select, SPC_SYSCALL, INT_ARG, ADDR_ARG, ADDR_ARG, ADDR_ARG, ADDR_ARG,
  257.      "select"},
  258.   {SYS_setdopt, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  259.      "setdopt"},
  260.   {SYS_fsync, UNIX_SYSCALL, FD_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "fsync"},
  261.   {SYS_setpriority, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  262.      "setpriority"},
  263.   {SYS_socket, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "socket"},
  264.   {SYS_connect, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  265.      "connect"},
  266.   {SYS_accept, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "accept"},
  267.   {SYS_getpriority, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  268.      "getpriority"},
  269.   {SYS_send, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "send"},
  270.   {SYS_recv, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "recv"},
  271.   {SYS_sigreturn, SPC_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  272.      "sigreturn"},
  273.   {SYS_bind, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "bind"},
  274.   {SYS_setsockopt, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  275.      "setsockopt"},
  276.   {SYS_listen, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "listen"},
  277.   {107, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  278.   {SYS_sigvec, SPC_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "sigvec"},
  279.   {SYS_sigblock, SPC_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  280.      "sigblock"},
  281.   {SYS_sigsetmask, SPC_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  282.      "sigsetmask"},
  283.   {SYS_sigpause, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  284.      "sigpause"},
  285.   {SYS_sigstack, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  286.      "sigstack"},
  287.   {SYS_recvmsg, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  288.      "recvmsg"},
  289.   {SYS_sendmsg, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  290.      "sendmsg"},
  291.   {115, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  292.   {SYS_gettimeofday, UNIX_SYSCALL, ADDR_ARG, ADDR_ARG, NO_ARG, NO_ARG, NO_ARG,
  293.      "gettimeofday"},
  294.   {SYS_getrusage, UNIX_SYSCALL, INT_ARG, ADDR_ARG, NO_ARG, NO_ARG, NO_ARG,
  295.      "getrusage"},
  296.   {SYS_getsockopt, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  297.      "getsockopt"},
  298.   {119, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  299.   {SYS_readv, UNIX_SYSCALL, FD_ARG, ADDR_ARG, INT_ARG, NO_ARG, NO_ARG,
  300.      "readv"},
  301.   {SYS_writev, UNIX_SYSCALL, FD_ARG, ADDR_ARG, INT_ARG, NO_ARG, NO_ARG,
  302.      "writev"},
  303.   {SYS_settimeofday, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  304.      "settimeofday"},
  305.   {SYS_fchown, UNIX_SYSCALL, FD_ARG, INT_ARG, INT_ARG, NO_ARG, NO_ARG,
  306.      "fchown"},
  307.   {SYS_fchmod, UNIX_SYSCALL, FD_ARG, INT_ARG, NO_ARG, NO_ARG, NO_ARG,
  308.      "fchmod"},
  309.   {SYS_recvfrom, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  310.      "recvfrom"},
  311.   {SYS_setreuid, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  312.      "setreuid"},
  313.   {SYS_setregid, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  314.      "setregid"},
  315.   {SYS_rename, UNIX_SYSCALL, STR_ARG, STR_ARG, NO_ARG, NO_ARG, NO_ARG,
  316.      "rename"},
  317.   {SYS_truncate, UNIX_SYSCALL, STR_ARG, INT_ARG, NO_ARG, NO_ARG, NO_ARG,
  318.      "truncate"},
  319.   {SYS_ftruncate, UNIX_SYSCALL, FD_ARG, INT_ARG, NO_ARG, NO_ARG, NO_ARG,
  320.      "ftruncate"},
  321.   {SYS_flock, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "flock"},
  322.   {132, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  323.   {SYS_sendto, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "sendto"},
  324.   {SYS_shutdown, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  325.      "shutdown"},
  326.   {SYS_socketpair, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  327.      "socketpair"},
  328.   {SYS_mkdir, UNIX_SYSCALL, STR_ARG, INT_ARG, NO_ARG, NO_ARG, NO_ARG, "mkdir"},
  329.   {SYS_rmdir, UNIX_SYSCALL, STR_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "rmdir"},
  330.   {SYS_utimes, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "utimes"},
  331.   {SYS_sigcleanup, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  332.      "sigcleanup"},
  333.   {SYS_adjtime, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  334.      "adjtime"},
  335.   {SYS_getpeername, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  336.      "getpeername"},
  337.   {SYS_gethostid, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  338.      "gethostid"},
  339.   {SYS_sethostid, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  340.      "sethostid"},
  341.   {SYS_getrlimit, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  342.      "getrlimit"},
  343.   {SYS_setrlimit, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  344.      "setrlimit"},
  345.   {SYS_killpg, UNIX_SYSCALL, INT_ARG, INT_ARG, NO_ARG, NO_ARG, NO_ARG,
  346.      "killpg"},
  347.   {147, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  348.   {SYS_setquota, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  349.      "setquota"},
  350.   {SYS_quota, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "quota"},
  351.   {SYS_getsockname, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  352.      "getsockname"},
  353.   {SYS_sysmips, SPC_SYSCALL, INT_ARG, INT_ARG, INT_ARG, INT_ARG, INT_ARG,
  354.      "sysmips"},
  355.   {SYS_cacheflush, SPC_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  356.      "cacheflush"},
  357.   {SYS_cachectl, SPC_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  358.      "cachectl"},
  359.   {154, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""},
  360.   {SYS_atomic_op, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG,
  361.      "atomic_op"},
  362. #else
  363.   0
  364. #endif
  365. };
  366.  
  367.  
  368. #define MAX_SYSCALL    (sizeof(syscall_table)/ sizeof(syscall_table[0]))
  369.  
  370.  
  371. static int syscall_usage[MAX_SYSCALL]; /* Track system calls */
  372.  
  373. #define SYSCALL_ARG(REGOFF, ARG, REG)                    \
  374.   ((syscall_table[R[REGOFF]].ARG == ADDR_ARG) ?                \
  375.      (R[REG] == 0 ? 0 : MEM_ADDRESS(R[REG])) :                \
  376.    (syscall_table[R[REGOFF]].ARG == STR_ARG) ? MEM_ADDRESS(R[REG])  :    \
  377.    (((syscall_table[R[REGOFF]].ARG == FD_ARG)                \
  378.      && (R[REG] < OPEN_MAX) && (R[REG] >= 0)))  ? prog_fds[R[REG]] : R[REG])
  379.  
  380. #define SYSCALL_COUNT(SYSCALL)                        \
  381.   if (SYSCALL < MAX_SYSCALL && SYSCALL >= 0) syscall_usage[SYSCALL]++;
  382.  
  383.  
  384.  
  385. /* Decides which syscall to execute or simulate.  Returns zero upon
  386.    exit syscall and non-zero to continue execution. */
  387.  
  388. #ifdef __STDC__
  389. int
  390. do_syscall (void)
  391. #else
  392. int
  393. do_syscall ()
  394. #endif
  395. {
  396.   SYSCALL_COUNT(R[REG_V0]);
  397.   if (source_file)
  398.     {
  399.       /* Syscalls for the source-language version of SPIM.  These are
  400.      easier to use than the real syscall and are portable to non-MIPS
  401.      (non-Unix?) operating systems. */
  402.  
  403.       switch (R[REG_V0])
  404.     {
  405.     case PRINT_INT_SYSCALL:
  406.       write_output (console_out, "%d", R[REG_A0]);
  407.       break;
  408.  
  409.     case PRINT_FLOAT_SYSCALL:
  410.       {
  411.         float val = FPR_S (REG_FA0);
  412.  
  413.         write_output (console_out, "%f", val);
  414.         break;
  415.       }
  416.  
  417.     case PRINT_DOUBLE_SYSCALL:
  418.       write_output (console_out, "%f", FPR[REG_FA0/2]);
  419.       break;
  420.  
  421.     case PRINT_STRING_SYSCALL:
  422.       write_output (console_out, "%s", MEM_ADDRESS (R[REG_A0]));
  423.       break;
  424.  
  425.     case READ_INT_SYSCALL:
  426.       {
  427.         static char str [256];
  428.  
  429.         read_input (str, 256);
  430.         R[REG_RES] = atol (str);
  431.         break;
  432.       }
  433.  
  434.     case READ_FLOAT_SYSCALL:
  435.       {
  436.         static char str [256];
  437.  
  438.         read_input (str, 256);
  439.         FGR [REG_FRES] = (float) atof (str);
  440.         break;
  441.       }
  442.  
  443.     case READ_DOUBLE_SYSCALL:
  444.       {
  445.         static char str [256];
  446.  
  447.         read_input (str, 256);
  448.         FPR [REG_FRES] = atof (str);
  449.         break;
  450.       }
  451.  
  452.     case READ_STRING_SYSCALL:
  453.       {
  454.         read_input ( (char *) MEM_ADDRESS (R[REG_A0]), R[REG_A1]);
  455.         break;
  456.       }
  457.  
  458.     case SBRK_SYSCALL:
  459.       {
  460.         mem_addr x = data_top;
  461.         expand_data (R[REG_A0]);
  462.         R[REG_RES] = x;
  463.         break;
  464.       }
  465.  
  466.     case EXIT_SYSCALL:
  467. #ifdef CL_SPIM
  468.       if (cycle_level) return (-1);
  469.       else
  470. #endif
  471.         return (0);
  472.  
  473.     default:
  474. #ifdef CL_SPIM
  475.       if (cycle_level) 
  476.         return (0);
  477. #endif
  478.       run_error ("Unknown system call: %d\n", R[REG_V0]);
  479.       break;
  480.     }
  481.     }
  482.   else
  483. #ifdef mips
  484.     {
  485. #ifdef CL_SPIM
  486.       if (!cycle_level)
  487. #endif
  488.     if (!fds_initialized)
  489.       {
  490.         initialize_prog_fds ();
  491.         fds_initialized = 1;
  492.       }
  493.  
  494.       /* Use actual MIPS system calls. First translate arguments from
  495.      simulated memory to actual memory and correct file descriptors. */
  496.       if (R[REG_V0] < 0 || R[REG_V0] > MAX_SYSCALL)
  497.     {
  498. #ifdef CL_SPIM
  499.       if (cycle_level)
  500.         return(0);
  501. #endif
  502.       run_error ("Illegal system call: %d\n", R[REG_V0]);
  503.     }
  504.  
  505.       switch (syscall_table[R[REG_V0]].syscall_type)
  506.     {
  507.     case BAD_SYSCALL:
  508. #ifdef CL_SPIM
  509.       if (cycle_level)
  510.         return(0);
  511. #endif
  512.       run_error ("Unknown system call: %d\n", R[REG_V0]);
  513.       break;
  514.  
  515.     case UNIX_SYSCALL:
  516.       unixsyscall ();
  517.       break;
  518.  
  519.     case SPC_SYSCALL:
  520.       /* These syscalls need to be simulated specially: */
  521.       switch (R[REG_V0])
  522.         {
  523.         case SYS_syscall:
  524.           R[REG_V0] = R[REG_A0];
  525.           R[REG_A0] = R[REG_A1];
  526.           R[REG_A1] = R[REG_A2];
  527.           R[REG_A2] = R[REG_A3];
  528.           READ_MEM_WORD (R[REG_A3], R[REG_SP] + 16);
  529. #ifdef CL_SPIM
  530.           if (cycle_level)
  531.         return (do_syscall());
  532. #endif
  533.           do_syscall ();
  534.           break;
  535.  
  536.         case SYS_sysmips:
  537.           {
  538.         /* The table smipst maps from the sysmips arguments to syscall
  539.            numbers */
  540.         int callno;
  541.         static int smipst[] = {7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  542.                      7, 7, SYS_getrusage, SYS_wait3,
  543.                      SYS_cacheflush, SYS_cachectl};
  544.         callno= R[REG_A0];
  545.         callno= ( (callno >0x100) ? smipst[callno - 0x100 + 10]
  546.              : smipst[callno]);
  547.         R[REG_V0] = callno;
  548.         R[REG_A0] = R[REG_A1];
  549.         R[REG_A1] = R[REG_A2];
  550.         R[REG_A2] = R[REG_A3];
  551.         READ_MEM_WORD (R[REG_A3], R[REG_SP] + 16);
  552. #ifdef CL_SPIM
  553.         if (cycle_level)
  554.           return (do_syscall());
  555. #endif    
  556.         do_syscall ();
  557.         break;
  558.           }
  559.  
  560.         case SYS_exit:
  561.           {
  562. #ifdef CL_SPIM
  563.         if (cycle_level)
  564.           {
  565.             write_output (message_out,
  566.                   "\nProgram exited with value (%d).\n",
  567.                   R[REG_A0]);
  568.             return (-1);
  569.           }
  570. #endif
  571.         kill_prog_fds ();
  572.  
  573.         return (0);
  574.           }
  575.  
  576.         case SYS_close:
  577.           if (unixsyscall () >= 0)
  578.         prog_fds[R[REG_A0]] = -1; /* Mark file descriptor closed */
  579.           break;
  580.  
  581.         case SYS_open:
  582.         case SYS_creat:
  583.         case SYS_dup:
  584.           {
  585.         int ret = unixsyscall ();
  586.  
  587.         if (ret >= 0)
  588.           prog_fds[ret] = ret; /* Update fd translation table */
  589.  
  590.         break;
  591.           }
  592.  
  593.         case SYS_pipe:
  594.           {
  595.         /* This isn't too useful unless we implement fork () or other
  596.            fd passing mechanisms */
  597.         int fd1, fd2;
  598.  
  599.         if (unixsyscall () >= 0)
  600.           {
  601.             READ_MEM_WORD (fd1, MEM_ADDRESS (R[REG_A0]));
  602.             READ_MEM_WORD (fd2, MEM_ADDRESS (R[REG_A0]));
  603.             prog_fds[fd1] = fd1;
  604.             prog_fds[fd2] = fd2;
  605.           }
  606.         break;
  607.           }
  608.  
  609.         case SYS_select:
  610.           {
  611.         int fd;
  612.         /*
  613.          * We have to use this kludge to circumvent typechecking
  614.          * because the memory read macros take the lefthand side
  615.          * as an argument instead of simply returnign the value
  616.          * at the address
  617.          */
  618.         long int kludge;
  619.         fd_set a, b, c;
  620.         fd_set *readfds = &a, *writefds = &b, *exceptfds = &c;
  621.         struct timeval *timeout;
  622.  
  623.         FD_ZERO (readfds);
  624.         FD_ZERO (writefds);
  625.         FD_ZERO (exceptfds);
  626.         READ_MEM_WORD (kludge, R[REG_SP] + 16);
  627.         if (kludge == NULL)
  628.           timeout = NULL;
  629.         else
  630.           timeout = (struct timeval *) MEM_ADDRESS (kludge);
  631.  
  632.         if (R[REG_A1] == NULL)
  633.           readfds = NULL;
  634.         else
  635.           for (fd = 0; fd < R[REG_A0]; fd++)
  636.             if (FD_ISSET (fd, (fd_set *) MEM_ADDRESS (R[REG_A1])))
  637.               FD_SET (prog_fds[fd], readfds);
  638.  
  639.         if (R[REG_A2] == NULL)
  640.           writefds = NULL;
  641.         else
  642.           for (fd = 0; fd < R[REG_A0]; fd++)
  643.             if (FD_ISSET (fd, (fd_set *) MEM_ADDRESS (R[REG_A2])))
  644.               FD_SET (prog_fds[fd], writefds);
  645.  
  646.         if (R[REG_A3] == NULL)
  647.           exceptfds = NULL;
  648.         else
  649.           for (fd = 0; fd < R[REG_A0]; fd++)
  650.             if (FD_ISSET (fd, (fd_set *) MEM_ADDRESS (R[REG_A3])))
  651.               FD_SET (prog_fds[fd], exceptfds);
  652.  
  653.         R[REG_RES] = select (R[REG_A0], readfds, writefds, exceptfds,
  654.                      timeout);
  655.         if (readfds == NULL)
  656.           R[REG_A1] = NULL;
  657.         else
  658.           for (fd = 0; fd < R[REG_A0]; fd++)
  659.             if (FD_ISSET (fd, readfds))
  660.               FD_SET (reverse_fds (fd),
  661.                   (fd_set *) MEM_ADDRESS (R[REG_A1]));
  662.  
  663.         if (writefds == NULL)
  664.           R[REG_A2] = NULL;
  665.         else
  666.           for (fd = 0; fd < R[REG_A0]; fd++)
  667.             if (FD_ISSET (fd, writefds))
  668.               FD_SET (reverse_fds (fd),
  669.                   (fd_set *) MEM_ADDRESS (R[REG_A2]));
  670.  
  671.         if (exceptfds == NULL)
  672.           R[REG_A3] = NULL;
  673.         else
  674.           for (fd = 0; fd < R[REG_A0]; fd++)
  675.             if (FD_ISSET (fd, exceptfds))
  676.               FD_SET (reverse_fds (fd),
  677.                   (fd_set *) MEM_ADDRESS (R[REG_A3]));
  678.  
  679.         if (R[REG_RES] < 0)
  680.           {
  681.             R[REG_ERR] = -1;
  682.             R[REG_RES] = errno;
  683.             return (-1);
  684.           }
  685.         else
  686.           {
  687.             R[REG_ERR] = 0;
  688.             return (R[REG_RES]);
  689.           }
  690.           }
  691.  
  692.         case SYS_sbrk:
  693.           {
  694.         expand_data (R[REG_A0]);
  695.         R[REG_RES] = program_break;
  696.         program_break += R[REG_A0];
  697.         R[REG_ERR] = 0;
  698.         break;
  699.           }
  700.  
  701.         case SYS_brk:
  702.           /* Round up to 4096 byte (page) boundary */
  703.           if ( ( (int) R[REG_A0] - (int) data_top) > 0)
  704.         expand_data (ROUND (R[REG_A0], 4096)- (int)data_top);
  705.           R[REG_RES] = program_break;
  706.           program_break = ROUND (R[REG_A0], 4096);
  707.           R[REG_ERR] = 0;
  708.           break;
  709.  
  710.         case SYS_sigvec:
  711.           {
  712.         int x;
  713.  
  714. #ifdef CL_SPIM
  715.         if (cycle_level) {
  716.           if (R[REG_A2] != 0) {
  717.             /* copy old sigvec data if structure is provided */
  718.             mem_addr tmp = MEM_ADDRESS(R[REG_A2]);
  719.             bcopy (&HANDLE(R[REG_A0]), tmp, sizeof(struct sigvec));
  720.           }
  721.           if (R[REG_A1] != 0) {
  722.             /* grab new sighandle information */
  723.             mem_addr tmp = MEM_ADDRESS(R[REG_A1]);
  724.             bcopy (tmp, &HANDLE(R[REG_A0]), sizeof(struct sigvec));
  725.             CATCH |= (1 << R[REG_A0]);
  726.           }
  727.           TRAMP(R[REG_A0]) = R[REG_A3];
  728.           R[REG_ERR] = 0;
  729.           break;
  730.         }
  731.         else
  732. #endif
  733.           {
  734.             if (R[REG_A2] != 0)
  735.               * (struct sigvec *) MEM_ADDRESS (R[REG_A2]) = sighandler[R[REG_A0]];
  736.             READ_MEM_WORD (x, R[REG_A1]);
  737.             sighandler[R[REG_A0]].sv_handler = (void (*) ()) x;
  738.             READ_MEM_WORD (x,R[REG_A1] + sizeof (int *));
  739.             sighandler[R[REG_A0]].sv_mask = x;
  740.             READ_MEM_WORD (x,R[REG_A1] + sizeof (int *)
  741.                    + sizeof (sigset_t));
  742.             sighandler[R[REG_A0]].sv_flags = x;
  743.             exception_address[R[REG_A0]] = R[REG_A3];
  744.             R[REG_ERR] = 0;
  745.             break;
  746.           }
  747.           }
  748.  
  749.         case SYS_sigreturn:
  750. #ifdef CL_SPIM
  751.           if (cycle_level)
  752.         dosigreturn (MEM_ADDRESS (R[REG_A0]));
  753.           else
  754. #endif
  755.         do_sigreturn (MEM_ADDRESS (R[REG_A0]));
  756.           R[REG_ERR] = 0;
  757.           break;
  758.  
  759.         case SYS_sigsetmask:
  760. #ifdef CL_SPIM
  761.           if (cycle_level) {
  762.         R[REG_RES] = MASK;
  763.         MASK = R[REG_A0];
  764.           }
  765.           else
  766. #endif
  767.         {
  768.           R[REG_RES] = prog_sigmask;
  769.           prog_sigmask = R[REG_A0];
  770.         }
  771.           R[REG_ERR] = 0;
  772.           break;
  773.  
  774.         case SYS_sigblock:
  775. #ifdef CL_SPIM
  776.           if (cycle_level) {
  777.         R[REG_RES] = MASK;
  778.         MASK |= R[REG_A0];
  779.           }
  780.           else
  781. #endif
  782.         {
  783.           R[REG_RES] = prog_sigmask;
  784.           prog_sigmask |= R[REG_A0];
  785.         }
  786.           R[REG_ERR] = 0;
  787.           break;
  788.  
  789.         case SYS_cacheflush:
  790. #if 0
  791.           R[REG_RES] = cache_flush ((void*)MEM_ADDRESS (R[REG_A0]),
  792.                     R[REG_A1],
  793.                     R[REG_A2]);
  794. #endif
  795.           R[REG_ERR] = 0;
  796.           break;
  797.  
  798.         case SYS_cachectl:
  799. #if 0
  800.           R[REG_RES] = cache_ctl ((void*)MEM_ADDRESS (R[REG_A0]),
  801.                       R[REG_A1],R
  802.                       [REG_A2]);
  803. #endif
  804.           R[REG_ERR] = 0;
  805.           break;
  806.  
  807.         default:
  808. #ifdef CL_SPIM
  809.           if (cycle_level)
  810.         return(0);
  811. #endif
  812.           run_error ("Unknown special system call: %d\n",R[REG_V0]);
  813.           break;
  814.         }
  815.       break;
  816.  
  817.     default:
  818. #ifdef CL_SPIM
  819.       if (cycle_level)
  820.         return(0);
  821. #endif
  822.       run_error ("Unknown type for syscall: %d\n", R[REG_V0]);
  823.       break;
  824.     }
  825.     }
  826. #else
  827.   run_error ("Can't use MIPS syscall on non-MIPS system\n");
  828. #endif
  829.  
  830.   return (1);
  831. }
  832.  
  833.  
  834.  
  835. /* Execute a Unix system call.  Returns negative on error. */
  836.  
  837. #ifdef __STDC__
  838. static int
  839. unixsyscall (void)
  840. #else
  841. static int
  842. unixsyscall ()
  843. #endif
  844. {
  845.   int arg0, arg1, arg2, arg3;
  846.  
  847.   arg0 = SYSCALL_ARG (REG_V0,arg0, REG_A0);
  848.   arg1 = SYSCALL_ARG (REG_V0,arg1, REG_A1);
  849.   arg2 = SYSCALL_ARG (REG_V0,arg2, REG_A2);
  850.   arg3 = SYSCALL_ARG (REG_V0,arg3, REG_A3);
  851.  
  852. #ifdef amiga /* There's no reason for us to get here, just over-anxious :) */ 
  853.   printf("Amiga warning: Unsupported syscall\n");
  854.   return -1;
  855. #else
  856.   R[REG_RES] = syscall (R[REG_V0], arg0, arg1, arg2, arg3);
  857. #endif
  858.   /* See if an error has occurred during the system call. If so, the
  859.      libc wrapper must be notifified by setting register 7 to be less than
  860.      zero and the return value should be errno. If not, register 7 should
  861.      be zero. r7 acts like the carry flag in the old days.  */
  862.  
  863.   if (R[REG_RES] < 0)
  864.     {
  865.       R[REG_ERR] = -1;
  866.       R[REG_RES] = errno;
  867.       return (-1);
  868.     }
  869.   else
  870.     {
  871.       R[REG_ERR] = 0;
  872.       return (R[REG_RES]);
  873.     }
  874. }
  875.  
  876.  
  877. #ifdef __STDC__
  878. static int
  879. reverse_fds (int fd)
  880. #else
  881. static int
  882. reverse_fds (fd)
  883.      int fd;
  884. #endif
  885. {
  886.   int i;
  887.  
  888.   for (i = 0; i < OPEN_MAX; i++)
  889.     if (prog_fds[i] == fd)
  890.       return (i);
  891.  
  892.   run_error ("Couldn't reverse translate fds\n");
  893.   return (-1);
  894. }
  895.  
  896.  
  897. #ifdef __STDC__
  898. void
  899. print_syscall_usage (void)
  900. #else
  901. void
  902. print_syscall_usage ()
  903. #endif
  904. {
  905.   int x;
  906.  
  907.   printf ("System call counts...\n\n");
  908.   printf ("Call#\t\tFrequency\n");
  909.   for (x = 0; x < MAX_SYSCALL; x ++)
  910.     if (syscall_usage[x] > 0)
  911.       printf("%d(%s)\t\t%d\n",
  912.          x, syscall_table[x].syscall_name, syscall_usage[x]);
  913.   printf ("\n");
  914. }
  915.  
  916.  
  917. #ifdef __STDC__
  918. void 
  919. initialize_prog_fds (void)
  920. #else
  921. void 
  922. initialize_prog_fds ()
  923. #endif
  924. {
  925.   int x;
  926.  
  927.   for (x = 0; x < OPEN_MAX; prog_fds[x++] = -1);
  928.   if (((prog_fds[0] = dup(0)) < 0) || 
  929.       ((prog_fds[1] = dup(1)) < 0) ||
  930.       ((prog_fds[2] = dup(2)) < 0))
  931.     error("init_prog_fds");
  932. }
  933.  
  934.  
  935. /* clear out programs file descriptors, close necessary files */
  936.  
  937. #ifdef __STDC__
  938. void 
  939. kill_prog_fds (void)
  940. #else
  941. void 
  942. kill_prog_fds ()
  943. #endif
  944. {
  945.   int x;
  946.  
  947.   for (x = 0; x < OPEN_MAX; x++)
  948.     if (prog_fds[x] != -1) close(prog_fds[x]);
  949. }
  950.  
  951.  
  952.  
  953. #ifdef __STDC__
  954. void
  955. handle_exception (void)
  956. #else
  957. void
  958. handle_exception ()
  959. #endif
  960. {
  961.   if (!quiet && ((Cause >> 2) & 0xf) != INT_EXCPT)
  962.     error ("Exception occurred at PC=0x%08x\n", EPC);
  963.  
  964.   exception_occurred = 0;
  965.   PC = EXCEPTION_ADDR;
  966.  
  967.   switch ((Cause >> 2) & 0xf)
  968.     {
  969.     case INT_EXCPT:
  970.       if (!source_file)
  971.     R[REG_A0] = SIGINT;
  972.       break;
  973.  
  974.     case ADDRL_EXCPT:
  975.       if (!source_file)
  976.     R[REG_A0] = SIGSEGV;
  977.       if (!quiet)
  978.     error ("  Unaligned address in inst/data fetch: 0x%08x\n",BadVAddr);
  979.       break;
  980.  
  981.     case ADDRS_EXCPT:
  982.       if (!source_file)
  983.     R[REG_A0] = SIGSEGV;
  984.       if (!quiet)
  985.     error ("  Unaligned address in store: 0x%08x\n", BadVAddr);
  986.       break;
  987.  
  988.     case IBUS_EXCPT:
  989.       if (!source_file)
  990.     R[REG_A0] = SIGBUS;
  991.       if (!quiet)
  992.     error ("  Bad address in text read: 0x%08x\n", BadVAddr);
  993.       break;
  994.  
  995.     case DBUS_EXCPT:
  996.       if (!source_file)
  997.     R[REG_A0] = SIGBUS;
  998.       if (!quiet)
  999.     error ("  Bad address in data/stack read: 0x%08x\n", BadVAddr);
  1000.       break;
  1001.  
  1002.     case BKPT_EXCPT:
  1003.       exception_occurred = 0;
  1004.       return;
  1005.  
  1006.     case SYSCALL_EXCPT:
  1007.       if (!quiet)
  1008.     error ("  Error in syscall\n");
  1009.       break;
  1010.  
  1011.     case RI_EXCPT:
  1012.       if (!quiet)
  1013.     error ("  Reserved instruction execution\n");
  1014.       break;
  1015.  
  1016.     case OVF_EXCPT:
  1017.       if (!source_file)
  1018.     R[REG_A0] = SIGFPE;
  1019.       if (!quiet)
  1020.     error ("  Arithmetic overflow\n");
  1021.       break;
  1022.  
  1023.     default:
  1024.       if (!quiet)
  1025.     error ("Unknown exception: %d\n", Cause >> 2);
  1026.       break;
  1027.     }
  1028.  
  1029.   if (!source_file)
  1030.     {
  1031. #ifdef mips
  1032.       if ((prog_sigmask & (1 << R[REG_A0])) == 1)
  1033.     return;
  1034.  
  1035.       if((int) sighandler[R[REG_A0]].sv_handler == 0)
  1036.     run_error ("Exception occurred at PC=0x%08x\nNo handler for it.\n",
  1037.            EPC);
  1038.  
  1039.       setup_signal_stack();
  1040.       R[REG_A1] = 48;
  1041.  
  1042.       R[REG_A2] = R[29];
  1043.       R[REG_A3] = (int) sighandler[R[REG_A0]].sv_handler;
  1044.       if ((PC = exception_address[R[REG_A0]]) == 0)
  1045.     PC = (int) find_symbol_address ("sigvec") + 44;
  1046. #endif
  1047.     }
  1048. }
  1049.  
  1050.  
  1051. #ifdef __STDC__
  1052. static void
  1053. setup_signal_stack (void)
  1054. #else
  1055. static void
  1056. setup_signal_stack ()
  1057. #endif
  1058. {
  1059. #ifdef mips
  1060.   int i;
  1061.   struct sigcontext *sc;
  1062.  
  1063.   R[29] -= sizeof(struct sigcontext) + 4;
  1064.   sc = (struct sigcontext *) MEM_ADDRESS (R[29]);
  1065.   sc->sc_onstack = 0        /**/;
  1066.   sc->sc_mask = prog_sigmask;
  1067.   sc->sc_pc = EPC;
  1068.   for(i=0; i < 32; ++i)        /* general purpose registers */
  1069.     sc->sc_regs[i] = R[i];
  1070.   sc->sc_mdlo = LO;        /* mul/div low */
  1071.   sc->sc_mdhi = HI;
  1072.   sc->sc_ownedfp = 0;        /* fp has been used */
  1073.   for(i=0; i < 32; ++i)        /* FPU registers */
  1074.     sc->sc_fpregs[i] = FPR[i];
  1075.   sc->sc_fpc_csr = 0;        /* floating point control and status reg */
  1076.   sc->sc_fpc_eir = 0;
  1077.   sc->sc_cause = Cause;        /* cp0 cause register */
  1078.   sc->sc_badvaddr = BadVAddr;    /* cp0 bad virtual address */
  1079.   sc->sc_badpaddr = 0;        /* cpu bd bad physical address */
  1080. #endif
  1081. }
  1082.  
  1083.  
  1084. #ifdef __STDC__
  1085. static void
  1086. do_sigreturn (mem_addr sigptr)
  1087. #else
  1088. static void
  1089. do_sigreturn (sigptr)
  1090.   mem_addr sigptr;
  1091. #endif
  1092. {
  1093. #ifdef mips
  1094.   int i;
  1095.   struct sigcontext *sc;
  1096.  
  1097.   sc = (struct sigcontext *) sigptr;
  1098.   prog_sigmask = sc->sc_mask;
  1099.   PC = sc->sc_pc - BYTES_PER_WORD;
  1100.   for(i=0; i < 32; ++i)
  1101.     R[i] = sc->sc_regs[i];
  1102.   LO = sc->sc_mdlo;
  1103.   HI = sc->sc_mdhi;
  1104.   for(i=0; i < 32; ++i)        /* FPU registers */
  1105.     FPR[i] = sc->sc_fpregs[i];
  1106.   Cause = sc->sc_cause;
  1107.   BadVAddr = sc->sc_badvaddr;
  1108.   R[29] += sizeof(struct sigcontext) + 4;
  1109. #endif
  1110. }
  1111.